// RMSClientSocket.cpp: implementation of the CRMSClientSocket class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#ifndef _VC10EA_

#ifdef _RMS_TRANSLATOR_
#include "..\RMSTranslator\resource.h"
#else //def _RMS_TRANSLATOR_
#include "resource.h"
#include "InCall.h"
#include "RMSServerDlg.h"
#endif //def _RMS_TRANSLATOR_

#endif //ndef _VC10EA_
#include "RMSBaseServer.h"
#include "RMSClientSocket.h"
#include "RMSWaveSocket.h"
#include "../Common/RMSLog.h"

#include "../RMSTomline/AuthServer/log.h"

#ifdef _RMS_TRANSLATOR_
#include "RMSTransPassword.h"
#endif

#ifndef _VC10EA_
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#endif //ndef _VC10EA_

#define SLEEP_CYCLE 0x10 * 5 // 10 cycles are not enough for slow or busy computers

#ifdef _RMS_TRANSLATOR_
	#include "..\RMSTranslator\RMSTranslatorDlg.h"
	#define GET_SERVER_DLG		((CRMSTranslatorDlg*)AfxGetMainWnd())
#else // def _RMS_TRANSLATOR_
///	#define GET_SERVER_DLG		((CRMSServerDlg*)AfxGetMainWnd())
#endif //def _RMS_TRANSLATOR_
#define getHomePath				GET_SERVER_DLG->getHomePath
#define saveHomePath			GET_SERVER_DLG->saveHomePath

#ifndef _RMS_TRANSLATOR_
 #if defined(_NET_VC_) || defined(VC70)
	#include "../GUI/Messages.h"
	extern HANDLE g_hNoVideoEnabled;
 #endif //def _NET_VC_ || VC70
#endif //ndef _RMS_TRANSLATOR_

#define MAX_MARKERS			200

#ifdef _RMS_TOML_
  #include "../RMSTomline/AuthServer/log.h"
  CLog* pLog;
#endif

// move include log.h to 22 line in this file. Because compile error occures. "log.h" included at that position in 2009/12/28 build.
// for debug only
// #if 0
//#include "../RMSTomline/AuthServer/log.h"
//CLog myLog("debug.log");
//CLog* pLog; = &myLog;
// #endif // #if 0


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//#define mydebug

//* debug begin
#ifdef mydebug
extern CMyDebug mdo;
#endif



int CRMSClientSocket::SendData(int Socket, void* Data,int nLen,int* Terminate)
{
	int n;
	int millis;

/*	if(pLog==NULL)
	{
	  pLog = new CLog("test.txt");
	}

_log(strtime() << nLen << "\n");*/

	if(!bitrateShaper.isItTimeToSendByTCP(&millis, nLen))
	{
		Sleep(millis);
	}

	n = send(Socket, (char*)Data, nLen, 0);

	if(n == SOCKET_ERROR) 
		return -1;

	bitrateShaper.countTCPPacketData(nLen);

	if(Terminate) 
		if(*Terminate)
			return -1;

	return n;
}

void CRMSClientSocket::setCallStatus(short status)
{
	RingStatus = status ? TAG_GOODFORMAT : TAG_BADFORMAT;
}


CRMSClientSocket::CRMSClientSocket(CBaseServer* p)
{
	pBaseServer=p;
	CameraID = -1;
	m_file = NULL;
	m_bActive = true;
	NewPassword = false;
	m_pData = new BYTE[0x200000];
	ResetData();
	RingString[0] = 0;
	Caller[0] = 0;
	m_szIP[0] = 0;
	lastSendSize=lastSendTime = 0xffffffff;
	m_byID = 0xff;
}

#define	pSzVideo		(pBaseServer->GetDataPtr_SizeVideo(CameraID))
#define	dtVideo			(pBaseServer->GetDataPtr_dtVideo(CameraID))
#define	pSzDate			(pBaseServer->GetDataPtr_SizeDate(CameraID))
#define	dtDate			(pBaseServer->GetDataPtr_dtDate(CameraID))
#define	pSzTime			(pBaseServer->GetDataPtr_SizeTime(CameraID))
#define	dtTime			(pBaseServer->GetDataPtr_dtTime(CameraID))
#define	pCriticalData	(pBaseServer->GetDataPtr_CriticalData(CameraID))
#define	pTypeVideo		(pBaseServer->GetDataPtr_TypeVideo(CameraID))

void CRMSClientSocket::ResetData()
{
}

void CRMSClientSocket::EnableNoVideo(BOOL bEnable)
{
	m_bNoVideoEnabled = bEnable;
_log(strtime()<<"(inside) changing novideo to "<< bEnable << "\n");
}

CRMSClientSocket::~CRMSClientSocket()
{
	Terminate(TRUE);
	if(m_file) fclose(m_file);
	if(m_pData) delete[] m_pData;
	m_pData = 0;
}

#define MAXTEST 0x4000
BOOL CRMSClientSocket::FindFrame(FILE* f, int nDirect) // 0 - Up, 1 Down
{
	DWORD dwTag;
	DWORD dwLen;
	BOOL result = FALSE;
	fpos_t lCur;
	fpos_t lRead;
	fpos_t lFind;
	BYTE* ptr;
	
	if(nDirect == 0)
	{
		while(!m_bQuit && !feof(f) && !result)
		{
			EnterCriticalSection(pCriticalData);
			fgetpos(f, &lCur);
			lRead = fread(m_pData, 1, MAXTEST, f);
			LeaveCriticalSection(pCriticalData);
			lFind = 0;
			ptr = m_pData;

			while(!m_bQuit && (lFind < lRead) && !result)
			{
				dwTag = 0;
				memcpy(&dwTag, ptr, sizeof(DWORD));
				switch(dwTag)
				{
				case TAG_STOREDDATA:
					result = TRUE;
					break;
				case TAG_TIMEMARK:
					lFind += sizeof(TimeMark);
					ptr += sizeof(TimeMark);
					break;
				case TAG_SIZE:
					lFind += sizeof(DWORD);
					ptr += sizeof(DWORD);
					break;
				case TAG_RMSSTOREDVIDEO_v01:
				case TAG_RMSSTOREDSOUND_v01:
				case TAG_STOREDTIME_v01:
				case TAG_STOREDDATE_v01:
					dwLen = 0;
					lFind += sizeof(DWORD);
					ptr += sizeof(DWORD);
					memcpy(&dwLen, ptr, sizeof(DWORD));
					lFind += sizeof(DWORD) + dwLen;
					ptr += sizeof(DWORD) + dwLen;
					break;
				default:
					lFind += 1;
					ptr += 1;
					break;
				}
			}
			if(result)
			{
				fpos_t pos = lCur + lFind;
				fsetpos(f, &pos);
			}
		}
	}
	else if(nDirect == 1)
	{
		while(!m_bQuit && !feof(f) && !result)
		{
			EnterCriticalSection(pCriticalData);
			fgetpos(f, &lCur);
			lCur -= MAXTEST;
			if(lCur < 0) lCur = 0;
			fsetpos(f, &lCur);
			fgetpos(f, &lCur);
			lRead = fread(m_pData, 1, MAXTEST, f);
			fsetpos(f, &lCur);
			LeaveCriticalSection(pCriticalData);
			lFind = 0;
			ptr = m_pData;

			while(!m_bQuit && (lFind < lRead) && !result)
			{
				dwTag = 0;
				memcpy(&dwTag, ptr, sizeof(DWORD));
				switch(dwTag)
				{
				case TAG_STOREDDATA:
					result = TRUE;
					break;
				case TAG_TIMEMARK:
					lFind += sizeof(TimeMark);
					ptr += sizeof(TimeMark);
					break;
				case TAG_SIZE:
					lFind += sizeof(DWORD);
					ptr += sizeof(DWORD);
					break;
				case TAG_RMSSTOREDVIDEO_v01:
				case TAG_RMSSTOREDSOUND_v01:
				case TAG_STOREDTIME_v01:
				case TAG_STOREDDATE_v01:
					dwLen = 0;
					lFind += sizeof(DWORD);
					ptr += sizeof(DWORD);
					memcpy(&dwLen, ptr, sizeof(DWORD));
					lFind += sizeof(DWORD) + dwLen;
					ptr += sizeof(DWORD) + dwLen;
					break;
				default:
					lFind += 1;
					ptr += 1;
					break;
				}
			}
			if(result)
			{
				fpos_t pos = lCur + lFind;
				fsetpos(f, &pos);
			}
		}
	}

	return result;
}

BOOL CRMSClientSocket::TimeCompare(FILE* f, TimeMark& tm, int& result)
{
	fpos_t lCur = 0;
	DWORD dwTag;
	DWORD dwLen;
	TimeMark tt;

	BOOL bRes = FALSE;
	BOOL stop = FALSE;
	BOOL AuthRequest=FALSE;

	EnterCriticalSection(pCriticalData);
	fgetpos(f, &lCur);
	fread(&dwTag, sizeof(DWORD), 1, f);
	LeaveCriticalSection(pCriticalData);
	if(dwTag != TAG_STOREDDATA) 
	{
		return FALSE;
	}

	while(!feof(f) && !m_bQuit && !stop)
	{
		dwTag = 0;
		EnterCriticalSection(pCriticalData);
		fread(&dwTag, sizeof(DWORD), 1, f);
		if(feof(f)) break;
		LeaveCriticalSection(pCriticalData);
		switch(dwTag)
		{
		case TAG_STOREDDATA:
			stop = TRUE;
			break;
		case TAG_TIMEMARK:
			EnterCriticalSection(pCriticalData);
			fread(&tt, sizeof(TimeMark), 1, f);
			LeaveCriticalSection(pCriticalData);
			result = tt.compare(tm);
			stop = TRUE;
			bRes = TRUE;
			break;
		case TAG_SIZE:
			EnterCriticalSection(pCriticalData);
			{ fpos_t tp; fgetpos(f, &tp); tp += sizeof(DWORD); fsetpos(f, &tp); }
			LeaveCriticalSection(pCriticalData);
			break;
		case TAG_RMSSTOREDVIDEO_v01:
		case TAG_RMSSTOREDSOUND_v01:
		case TAG_STOREDTIME_v01:
		case TAG_STOREDDATE_v01:
			dwLen = 0;
			EnterCriticalSection(pCriticalData);
			fread(&dwLen, sizeof(DWORD), 1, f);
			{ fpos_t tp; fgetpos(f, &tp); tp += dwLen; fsetpos(f, &tp); }
			LeaveCriticalSection(pCriticalData);
			break;
		default:
			stop = TRUE;
			break;
		}
	}
	fsetpos(f, &lCur);
	return bRes;
}

DWORD CRMSClientSocket::GetFrameLength(FILE* f)
{
	fpos_t lCur = 0;
	fpos_t lEnd = 0;
	DWORD dwTag;
	DWORD dwLen;
	BOOL stop = FALSE;

	EnterCriticalSection(pCriticalData);
	fgetpos(f, &lCur);
	fread(&dwTag, sizeof(DWORD), 1, f);
	LeaveCriticalSection(pCriticalData);
	if(dwTag != TAG_STOREDDATA) 
	{
		return 0;
	}

	while(!feof(f) && !m_bQuit && !stop)
	{
		dwTag = 0;
		EnterCriticalSection(pCriticalData);
		fread(&dwTag, sizeof(DWORD), 1, f);
		LeaveCriticalSection(pCriticalData);
		if(feof(f)) break;
		switch(dwTag)
		{
		case TAG_STOREDDATA:
			stop = TRUE;
			break;
		case TAG_TIMEMARK:
			EnterCriticalSection(pCriticalData);
			{ fpos_t tp; fgetpos(f, &tp); tp += sizeof(TimeMark); fsetpos(f, &tp); }
			LeaveCriticalSection(pCriticalData);
			break;
		case TAG_SIZE:
			EnterCriticalSection(pCriticalData);
			{ fpos_t tp; fgetpos(f, &tp); tp += sizeof(DWORD); fsetpos(f, &tp); }
			LeaveCriticalSection(pCriticalData);
			break;
		case TAG_RMSSTOREDVIDEO_v01:
		case TAG_RMSSTOREDSOUND_v01:
		case TAG_STOREDTIME_v01:
		case TAG_STOREDDATE_v01:
			dwLen = 0;
			EnterCriticalSection(pCriticalData);
			fread(&dwLen, sizeof(DWORD), 1, f);
			{ fpos_t tp; fgetpos(f, &tp); tp += dwLen; fsetpos(f, &tp); }
			LeaveCriticalSection(pCriticalData);
			break;
		default:
			return 0;
		}
	}
	EnterCriticalSection(pCriticalData);
	fgetpos(f, &lEnd);
	lEnd -= 4;
	fsetpos(f, &lCur);
	LeaveCriticalSection(pCriticalData);
	return (lEnd - lCur);
}

string INT2STR(int i)
{
  ostringstream res;
  res << (char)i << (char)(i>>8) << (char)(i>>16) << (char)(i>>24);
  return res.str();
};


BOOL CRMSClientSocket::GetClientRequest()
{
	BOOL result = TRUE;
	int iRes = 0;

	DWORD dwTag;
	DWORD dwCol;
	DWORD dwLen;
	DWORD newAddr = 0L;
	DWORD* Request = (DWORD*)m_pData;


	BOOL bBroadcastMode = TRUE;
	BOOL AuthRequest= FALSE;
	BOOL wasRing=FALSE;

	BOOL enableRing=FALSE;

	int kbps = 0;
	char* tmp;
	
	char pass[128];
	int n;


	// Old Nadya's hack. Remove in final realease!
	#define AUTH_MAGIC 1234	
	DWORD AuthTagCounter=AUTH_MAGIC;
	//=====================================

	// clear all
	CameraID = -1;pass[0]=0;Caller[0]=0;
	m_bSupportRing=m_bVideo = m_bAudio = m_bTime = m_bDate = m_bTimeMark = m_bTimeMark1 = FALSE;
	memset(RingString,0,sizeof(RingString));

	if(recv(m_clientSocket, (char*)&dwTag, 4, 0) == SOCKET_ERROR)
	{
		return FALSE;
	}
	if(dwTag != TAG_REQUEST)
	{
		return FALSE;
	}

	if(recv(m_clientSocket, (char*)&dwCol, 4, 0) == SOCKET_ERROR)
	{
		return FALSE;
	}

	AuthTagCounter += dwCol;
_log("GetClientReuest\n");
	// process request
	while(dwCol>0)
	{
		dwTag = 0;
		n = recv(m_clientSocket, (char*)&dwTag, 4, 0);
		if(n == SOCKET_ERROR)
		{
			return FALSE;
		}
		
		dwLen = 0;
		n = recv(m_clientSocket, (char*)&dwLen, sizeof(DWORD), 0);
		if(n == SOCKET_ERROR)
		{
			return FALSE;
		}

_log(dwCol << ". tag/len = "<<INT2STR(dwTag)<<"/"<<dwLen<<"\n");

		dwCol--;
		switch(dwTag)
		{
		// Video over UDP
		case TAG_VIDEOSTREAM_v01:
		// Video over TCP
		case TAG_RMSVIDEO_v01:
			Write2Log1("TAG_RMSVIDEO_v01","");
			m_bStored = FALSE;
			m_bVideo = TRUE;
			m_dwTypeVideo = dwTag;
			AuthTagCounter--;
#ifndef _RMS_TRANSLATOR_
 #if defined(_NET_VC_) || defined(VC70)
_log("New Client!\n");
//_log("dlg: "<<GET_SERVER_DLG->m_bVideo<<"\n");

//CRMSServerDlg* pdlg = GET_SERVER_DLG;
//BOOL b = pdlg->m_bVideo;
//EnableNoVideo(!b);

EnableNoVideo(!GET_SERVER_DLG->m_bVideo);



//EnableNoVideo(!GET_SERVER_DLG->m_bVideo);
			::PostMessage(GET_SERVER_DLG->GetSafeHwnd(),
			  WM_CLIENT_CONNECTED, (WPARAM)m_byID, (LPARAM)0);


/*			EnableNoVideo(FALSE);
			if(dwLen != 0)
			{
				if(GET_SERVER_DLG->m_bVideo)
				{
					EnableNoVideo(TRUE);
				}
				else
				{
					::PostMessage(GET_SERVER_DLG->GetSafeHwnd(),
								  WM_CLIENT_CONNECTED, (WPARAM)m_byID, (LPARAM)0);
				}
			}*/
 #endif //def defined(_NET_VC_) || defined(VC70)
#else //ndef _RMS_TRANSLATOR_
			EnableNoVideo(dwLen != 0);
#endif //ndef _RMS_TRANSLATOR_
			break;
		case TAG_RMSSTOREDVIDEO_v01:
			Write2Log1("TAG_RMSSTOREDVIDEO_v01","");
			m_bStored = TRUE;
			m_bVideo = TRUE;
			m_dwTypeVideo = dwTag;
			break;
		case TAG_RMSSTOREDSOUND_v01:
			Write2Log1("TAG_RMSSTOREDSOUND_v01","");
			m_bStored = TRUE;
			m_bAudio = TRUE;
			m_dwTypeVideo = dwTag;
			break;
		// Audio
		case TAG_RMSSOUND_v01:
			Write2Log1("TAG_RMSSOUND_v01","");
			m_bAudio = TRUE;
			m_dwTypeAudio = dwTag;
			break;
		// Time
		case TAG_TIME_v01:
			Write2Log1("TAG_TIME_v01","");
			m_bTime = TRUE;
			m_dwTypeTime = dwTag;
			break;
		case TAG_STOREDTIME_v01:
			Write2Log1("TAG_STOREDTIME_v01","");
			m_bTime = TRUE;
			m_dwTypeTime = dwTag;
			break;
		case TAG_AUTHREQ:
			Write2Log1("TAG_AUTHREQ","");
			if(dwLen != 0)
			{
				return FALSE;
			}
			AuthTagCounter--;
			AuthRequest=TRUE;
			break;
		case TAG_PASSWORD_v01:
			if(dwLen > 128)
			{
				return FALSE;
			}
			n = recv(m_clientSocket, (char*)pass, dwLen, 0);
			Write2Log1("TAG_PASSWORD_v01 received ",pass);

			if(n == SOCKET_ERROR)
			{
				return FALSE;
			}
			AuthTagCounter--;
#ifndef _RMS_TRANSLATOR_
			// ENCODER
#ifndef _VC10EA_
			RingStatus = enableRing ? -1 : 0;
			::PostMessage(AfxGetApp()->m_pMainWnd->GetSafeHwnd(),
						  IDC_INCALL, (LONG)RingString, (LONG)&RingStatus);
			while((RingStatus == 0) || (RingStatus == -1))
			{
				int wait = TAG_CONFWAIT;
				if (m_bQuit) { return FALSE; } 
				Sleep(100);
				if (SendData(m_clientSocket,&wait,4,0)<0) return FALSE;
			}
#else //ndef _VC10EA_
			{
				RingStatus = (!((CVC10EACtrl*)pBaseServer)->m_broadcastMode)
							 ? ((CVC10EACtrl*)pBaseServer)->OnCall((long)m_dwID, RingString, enableRing)
							 : TAG_BROADCAST;
				for(int k = 0; (k < (12000/100)) && (RingStatus == 0); k++)
				{ // waits for an approval up to 12 seconds
					DWORD wait = TAG_CONFWAIT;
					if(m_bQuit) { return FALSE; } 
					Sleep(100);
					if(SendData(m_clientSocket, &wait, sizeof(wait), 0) < 0) return FALSE;
				}
			}
#endif //ndef _VC10EA_

			if(RingStatus == TAG_GOODFORMAT) bBroadcastMode = FALSE;	// accepted & conference mode		
			else if(RingStatus == TAG_BROADCAST) bBroadcastMode = TRUE;	// broadcast mode
			else result = FALSE;

			if( result )
			{
				if(wasRing && !bBroadcastMode)
				{ // no need to check password
				}
				else
				{ // Encoder, just check password
					if( pBaseServer->GetPasswordLen() > 0 )
					{
						if( !pBaseServer->CheckPassword(pass) )
						{
							result = FALSE;
						}
					}
					else
					{ // accept all calls on empty password on encoder
					}
				}
			}
#endif
			if(result)
			{
				kbps = 0;
				tmp = new char[128];
				sscanf(RingString, "%s %s %s %s %s %s %s %s %s %s %i %s %s",
					   tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, &kbps, tmp, tmp);
				delete tmp;
				if(kbps == 0) kbps = 500; // default
				bitrateShaper.setTargetBitrate((float)kbps);
			}
			break;
		case TAG_VC_RING:
		{
			if ( (dwLen > sizeof(RingString)) || (dwLen <= 0) ) return FALSE;
			wasRing=TRUE;
			n = recv(m_clientSocket, (char*)RingString, dwLen, 0);
			if(n == SOCKET_ERROR)
			{
				return FALSE;
			}
#ifndef _RMS_TRANSLATOR_
#if defined(_OEM_) && defined(_TEC_)
			strcpy(RingStringCopy, RingString);
#endif //defined(_OEM_) && defined(_TEC_)
#endif //ndef _RMS_TRANSLATOR_
			AuthTagCounter--;
			Write2Log1("TAG_VC_RING",RingString);
#ifdef _RMS_TRANSLATOR_
			// Ring the camera, to check if it will accept, or in broadcast mode
			CInfo info;
			if(!pBaseServer->GetCameraInfo(CameraID, info)) return FALSE;

			CRMSTransPassword* TransPassword;
			TransPassword = new CRMSTransPassword(pBaseServer,
									RingString, info, TAG_VC_RING);
			TransPassword->Execute();				
			while(TransPassword->PassStatus == 0)
			{ 
				int wait = TAG_CONFWAIT;
				if(m_bQuit)
				{
					return FALSE;
				}
				Sleep(100);
				if(SendData(m_clientSocket, &wait, 4, 0) < 0)
					return FALSE;
			}
			result = (TransPassword->PassStatus == TAG_GOODFORMAT);

			// change IP addr of camera to received from next server in a chain
			newAddr = pBaseServer->checkReturnedAddress(CameraID,
														m_saClient.sin_addr.S_un.S_addr,
														TransPassword->getReturnedAddrIf());
			delete TransPassword;

			// if server / translator request, send TAG_ANSWER
			if(result && ((AuthTagCounter == AUTH_MAGIC) || AuthRequest))
			{
				DWORD answer[] = { TAG_ANSWER, TAG_GOODFORMAT, 1,
								   TAG_ADDRESS_ON_RING, 4, newAddr ^ (DWORD)CInfo::KEY };
				if(SendData(m_clientSocket, answer, sizeof(answer), 0) < 0)
					return 0;

				return AUTH_MAGIC;
			}
#else
			// Encoder --------- check for broadcast mode
			newAddr = pBaseServer->getSelectedAddr();
			if(((AuthTagCounter==AUTH_MAGIC)||AuthRequest))
			{
				DWORD answer[] = { TAG_ANSWER, TAG_GOODFORMAT, 1,
								   TAG_ADDRESS_ON_RING, 4, newAddr ^ (ULONG)CInfo::KEY };
				SendData(m_clientSocket, answer, sizeof(answer), 0);
				return AUTH_MAGIC;
			}						
#endif
			break;
		}
		case TAG_VC_RING_1:
			if ( (dwLen > sizeof(RingString)) || (dwLen <= 0) ) return FALSE;
			wasRing=TRUE;
			n = recv(m_clientSocket, (char*)RingString, dwLen, 0);
			if(n == SOCKET_ERROR)
			{
				return FALSE;
			}

#ifndef _RMS_TRANSLATOR_
#if defined(_OEM_) && defined(_TEC_)
			strcpy(RingStringCopy, RingString);
#endif //defined(_OEM_) && defined(_TEC_)
#endif //ndef _RMS_TRANSLATOR_

			kbps = 0;
			tmp = new char[128];
			sscanf(RingString, "%s %s %s %s %s %s %s %s %s %s %i %s %s",
				   tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp, &kbps, tmp, tmp);
			delete tmp;
			if(kbps == 0) kbps = 500; // default
			bitrateShaper.setTargetBitrate((float)kbps);

			AuthTagCounter--;
			Write2Log1("TAG_VC_RING_1",RingString);
			newAddr = pBaseServer->getSelectedAddr();
			break;
		case TAG_CAMERA_v01:
			if(dwLen != sizeof(DWORD))
			{
				return FALSE;
			}

			n = recv(m_clientSocket, (char*)&CameraID, sizeof(int), 0);
			if(n == SOCKET_ERROR)
			{
				return FALSE;
			}
			Write2Log2("TAG_CAMERA_v01, ID=",CameraID);
			if(pBaseServer->GetMaxCameras() == 1)
			{
				CameraID = 0;
			}
			break;
#if defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)
		case TAG_TIMEMARK1:
			if(dwLen != (2*sizeof(TimeMark)))
			{
				return FALSE;
			}
			Write2Log1("TAG_TIMEMARK1", "");
			m_bTimeMark1 = TRUE;
			n = recv(m_clientSocket, (char*)&m_timeFrom, sizeof(TimeMark), 0);
			if(n == SOCKET_ERROR)
			{
				return FALSE;
			}
			TCHAR chtime[32];
			Write2Log1("  timeFrom: ", m_timeFrom.toString(chtime));
			n = recv(m_clientSocket, (char*)&m_timeTo, sizeof(TimeMark), 0);
			if(n == SOCKET_ERROR)
			{
				return FALSE;
			}
			Write2Log1("  timeTo: ", m_timeTo.toString(chtime));
			m_bGetRecords = FALSE;
			break;
#endif //defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)
		case TAG_TIMEMARK:
			{
			if(dwLen != (2*sizeof(TimeMark)))
			{
				return FALSE;
			}
			Write2Log1("TAG_TIMEMARK","");
			m_bTimeMark = TRUE;
			m_dwTypeTimeMark = dwTag;
			n = recv(m_clientSocket, (char*)&m_timeStart, sizeof(TimeMark), 0);
			if(n == SOCKET_ERROR)
			{
				return FALSE;
			}
			TCHAR chtime[32];
			Write2Log1("  timeStart: ", m_timeStart.toString(chtime));
			n = recv(m_clientSocket, (char*)&m_timeEnd, sizeof(TimeMark), 0);
			if(n == SOCKET_ERROR)
			{
				return FALSE;
			}
			Write2Log1("  timeEnd: ", m_timeEnd.toString(chtime));

#ifdef _CYCLIC_BUFFER_
			int i;
			int cycle = pBaseServer->GetRecordCycle();
			CTime timeCur((int)m_timeEnd.dwYear,
						  (int)m_timeEnd.bMonth,
						  (int)m_timeEnd.bDay,
						  (int)m_timeEnd.bHour,
						  (int)m_timeEnd.bMinute,
						  (int)m_timeEnd.bSecond);
			CTimeSpan timeSpan(1,0,0,0);

			CString temp;
			for(i=0; i<cycle-1; i++) timeCur -= timeSpan;

			FILE* f = NULL;
			BOOL finded = FALSE;

			fpos_t lBeginPosition, lEndPosition, lTestPosition;
			fpos_t lFindFirst = 0;
			fpos_t lFindLast = 0;
			m_lFindTotal = 0;
			m_lBeginPosition = 0;
			m_lEndPosition = 0;
			
			for(i = 0; i<cycle; i++)
			{
				if(CameraID)
				{
					m_strBeginFile.Format("%i%s", CameraID, (LPCTSTR)timeCur.Format("%b%d%Y.rms"));
				}
				else
				{
					m_strBeginFile = timeCur.Format("%b%d%Y.rms");
				}

				CString hp = getHomePath();
				hp += "\\";
				hp += m_strBeginFile;
				f = fopen(hp, "rb");
				if(f)
				{
					// Find first frame
					fseek(f, 0L, SEEK_SET);
					fgetpos(f, &lBeginPosition);
					if(TimeCompare(f, m_timeStart, iRes) && (iRes >= 0))
					{
						fgetpos(f, &m_lBeginPosition);
						finded = TRUE;
					}
					else
					{
						fpos_t tp; tp = _filelengthi64(fileno(f)); fsetpos(f, &tp);
						if(!FindFrame(f, 1)) continue;
						fgetpos(f, &lEndPosition);
						if(TimeCompare(f, m_timeStart, iRes) && (iRes >= 0))
						{
							finded = TRUE;
							while(!feof(f) && !m_bQuit)
							{
								fsetpos(f, &lBeginPosition);
								if((lEndPosition - lBeginPosition) <= GetFrameLength(f))
								{
									m_lBeginPosition = lEndPosition;
									lFindFirst = lEndPosition;
									break;
								}

								lTestPosition = lBeginPosition + (lEndPosition - lBeginPosition) / 2;
								fsetpos(f, &lTestPosition);
								if(!FindFrame(f, 0)) goto stop_search;

								fgetpos(f, &lTestPosition);
								if(lTestPosition == lBeginPosition)
								{
									m_lBeginPosition = lBeginPosition;
									lFindFirst = lBeginPosition;
									break;
								}
								if(lTestPosition == lEndPosition)
								{
									m_lBeginPosition = lEndPosition;
									lFindFirst = lEndPosition;
									break;
								}
								
								if(TimeCompare(f, m_timeStart, iRes) && (iRes >= 0))
								{
									lEndPosition = lTestPosition;
								}
								else
								{
									lBeginPosition = lTestPosition;
								}
							}
						}
					}
					if(f)
					{
						fclose(f);
						f = NULL;
					}
				}
				if(finded)
				{
					break;
				}
				timeCur += timeSpan;
			}

			if(finded)
			{
				if(CameraID)
				{
					m_strEndFile.Format("%i%s", CameraID, (LPCTSTR)timeCur.Format("%b%d%Y.rms"));
				}
				else
				{
					m_strEndFile = timeCur.Format("%b%d%Y.rms");
				}

				for(; i<cycle; i++)
				{
					if(CameraID)
					{
						temp.Format("%i%s", CameraID, (LPCTSTR)timeCur.Format("%b%d%Y.rms"));
					}
					else
					{
						temp = timeCur.Format("%b%d%Y.rms");
					}

					CString hp = getHomePath();
					hp += "\\";
					hp += temp;
					f = fopen(hp, "rb");
					if(f)
					{
						// Find Last frame
						m_strEndFile = temp;

						fseek(f, 0L, SEEK_SET);
						fgetpos(f, &lBeginPosition);
						lEndPosition = _filelengthi64(fileno(f)); fsetpos(f, &lEndPosition);

						if(!FindFrame(f, 1)) goto stop_search;

						if(TimeCompare(f, m_timeEnd, iRes) && (iRes < 0))
						{
							fgetpos(f, &lFindLast);
							fsetpos(f, &lEndPosition);
							lFindLast = lEndPosition + GetFrameLength(f);
							if(!m_lFindTotal)
							{
								m_lFindTotal = lFindLast - lFindFirst;
							}
							else
							{
								m_lFindTotal += lFindLast;
							}
							m_lEndPosition = lFindLast;
						}
						else
						{
							while(!feof(f) && !m_bQuit)
							{
								fsetpos(f, &lBeginPosition);
								if((lEndPosition - lBeginPosition) <= GetFrameLength(f))
								{
									fsetpos(f, &lBeginPosition);
									lFindLast = lBeginPosition + GetFrameLength(f);
									m_lEndPosition = lFindLast;
									if(!m_lFindTotal)
									{
										m_lFindTotal = lFindLast - lFindFirst;
									}
									else
									{
										m_lFindTotal += lFindLast;
									}
									goto stop_search;
								}

								lTestPosition = lBeginPosition + (lEndPosition - lBeginPosition) / 2;
								fsetpos(f, &lTestPosition);
								if(!FindFrame(f, 0)) goto stop_search;

								fgetpos(f, &lTestPosition);
								if(lTestPosition == lBeginPosition)
								{
									fsetpos(f, &lBeginPosition);
									lFindLast = lBeginPosition + GetFrameLength(f);
									m_lEndPosition = lFindLast;
									if(!m_lFindTotal)
									{
										m_lFindTotal = lFindLast - lFindFirst;
									}
									else
									{
										m_lFindTotal += lFindLast;
									}
									goto stop_search;
								}
								if(lTestPosition == lEndPosition)
								{
									fsetpos(f, &lEndPosition);
									lFindLast = lEndPosition + GetFrameLength(f);
									m_lEndPosition = lFindLast;
									if(!m_lFindTotal)
									{
										m_lFindTotal = lFindLast - lFindFirst;
									}
									else
									{
										m_lFindTotal += lFindLast;
									}
									goto stop_search;
								}
								
								if(TimeCompare(f, m_timeEnd, iRes) && (iRes >= 0))
								{
									lEndPosition = lTestPosition;
								}
								else
								{
									lBeginPosition = lTestPosition;
								}
							}
						}
					}
					if(f)
					{
						fclose(f);
						f = NULL;
					}
					timeCur += timeSpan;
				}
			}
stop_search:
			if(f)
			{
				fclose(f);
				f = NULL;
			}
#else
#if defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)
			m_lFindTotal = 1;
			m_bGetRecords = FALSE;
#else //defined(_RMS_TRANSLATOR_) && !defined(_JNC_REC_)
			CString temp;
			if(CameraID)
			{
				temp.Format("%i",CameraID);
				temp += "stored_video.rms";
			}
			else
			{
				temp = "stored_video.rms";
			}
			CString hp = "";
#ifndef _VC10EA_
			hp = getHomePath();
			if(!hp.IsEmpty()) hp += "\\";
#endif //ndef _VC10EA_
			hp += temp;
			FILE* f = fopen(hp,"rb");
			if(f)
			{
				getStartPosition(f);
				fclose(f);
				f = NULL;
			}
			else
			{
				m_lFindTotal = 0;
			}
#endif //defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)
#endif
			}
			break;
		// Date		
		case TAG_DATE_v01:
			Write2Log1("TAG_DATE_v01","");
			m_bDate = TRUE;
			m_dwTypeDate = dwTag;
			break;
		case TAG_STOREDDATE_v01:
			Write2Log1("TAG_STOREDDATE_v01","");
			m_bDate = TRUE;
			m_dwTypeDate = dwTag;
			break;
		// support ring
		case TAG_SUPPORT_RING:
			Write2Log1("TAG_SUPPORT_RING","");
			m_bSupportRing=TRUE;
			enableRing = (BOOL)dwLen;
			break;
#if defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)
		// get records list
		case TAG_GETRECORDS:
			Write2Log1("TAG_GETRECORDS", "");
			m_bGetRecords = TRUE;
			break;
#endif //defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)
		// unknown tag
		default:
			Write2Log2("UNKNOWN TAG, TAG=", dwTag);
			Write2Log2("             LEN=", dwLen);
			if(dwLen)
			{
				n = recv(m_clientSocket, (char*)m_pData, dwLen, 0);
				if(n == SOCKET_ERROR)
				{
					return FALSE;
				}
			}
			break;
		}
		if(m_bQuit) return FALSE;
	}

#ifdef _IPR_
	if (pBaseServer->m_bEnableIpr)
	{
		if(!IsRegistedIP(m_saClient.sin_addr))
		{
			result = false;
			CString ip = inet_ntoa(m_saClient.sin_addr);
			TRACE1("%s - CRMSClientSocket::ThreadFunc() - send refuse(-ipr)\n", ip);
		}
	}
#endif // _IPR_

	if(result)
	{
		if(!m_bVideo)
		{
			result = FALSE;
		}
		else
		{
			if(m_bStored)
			{
				if(m_lFindTotal)
				{
					result = TRUE;
				}
				else
				{
					result = FALSE;
				}
			}
			else
			{
				result = TRUE;
			}
		}

		if(!m_bStored && result && (AuthTagCounter!=AUTH_MAGIC)&&(AuthRequest==0))
		{
#ifdef _RMS_TRANSLATOR_
			Write2Log1("Setting up CVideoCameraStream thread; caller:", RingString);

			if(pass[0] != 0)
				pBaseServer->SetCamPassword(CameraID, pass);

			BOOL ret = TRUE;
			HANDLE harr[2] = { CreateEvent(NULL, FALSE, FALSE, NULL),
							   CreateEvent(NULL, FALSE, FALSE, NULL) };

			int rs = pBaseServer->CheckStartCamera(CameraID, m_bNoVideoEnabled,
													harr[0], harr[1],
													enableRing, RingString);
			result = (rs > 0);
			if(rs == 1)
			{
				DWORD stat = TAG_CONFWAIT;
				while(ret && (stat == TAG_CONFWAIT))
				{
					if(m_bQuit)
					{
						ret = FALSE;
						break;
					}
					DWORD wr = WaitForMultipleObjects(2, harr, FALSE, 100);
					if(wr != WAIT_TIMEOUT)
					{
						result = ((wr - WAIT_OBJECT_0) == 1);
						stat = 0;
						Write2Log1("Camera - ", result ? "sending started" : "failed to start");
					}
					else
					{
						ret = !(SendData(m_clientSocket, &stat, sizeof(stat), 0) < 0);
					}
				}
			}
			CloseHandle(harr[0]);
			CloseHandle(harr[1]);
			if(!ret)
				return FALSE;

			if(result) ResetData();
#else
			if(pBaseServer->CheckStartCamera(CameraID) < 0) {
				result =  FALSE;
			}else{	
				ResetData();
			}
#endif
		}
	}

	// send result ----------------------

	dwLen = sizeof(DWORD)*2;
	int t=0;
	Request[t++] = TAG_ANSWER;
	if(result)
	{
		// if it is new client - supports ring functionality,
		// inform client that we do support ring too
		if(m_bSupportRing)
		{
			dwLen+= sizeof(DWORD);
			Request[t++]=TAG_SUPPORT_RING;
		}

		if(!m_bStored)
		{ //--------- live video --------------------------
			BOOL bVideo = (m_dwTypeVideo == TAG_VIDEOSTREAM_v01) ||
						  (m_dwTypeVideo == TAG_VIDEOSTREAM_v02);
			if(m_bAudio || bVideo)
			{
				int nPort;
				CRMSWaveSocket* pWaveSocket = new CRMSWaveSocket(pBaseServer, this);
				pWaveSocket->m_byID = m_byID;
				pWaveSocket->CameraID = CameraID;
				pWaveSocket->pBaseServer= pBaseServer;
				pWaveSocket->m_dwTypeAudio = m_dwTypeAudio;
				pWaveSocket->m_dwTypeVideo = m_dwTypeVideo;
				
				if(nPort = pWaveSocket->StartWaveSession(m_saServer, m_bAudio, bVideo))
				{
					pBaseServer->AddWaveSocket(pWaveSocket);
					dwLen += sizeof(DWORD) + sizeof(int);
					Request[t++] = TAG_SOUNDUDPPORT;
					Request[t++] = (DWORD) nPort;
					Request[t++] = TAG_GOODFORMAT;
				}
				else
				{
					Request[t++] = TAG_GOODFORMAT;
					TRACE0("Unable to start audio session\n");
					delete pWaveSocket;
				}
			}
			else
			{
				Request[t++] = TAG_GOODFORMAT;
			}
			// reflect returned address to initiator
			int t0 = t;
			Request[t++] = 1;
			Request[t++] = TAG_ADDRESS_ON_RING;
			Request[t++] = sizeof(DWORD);
			Request[t++] = newAddr ^ (ULONG)CInfo::KEY;
			dwLen += (t - t0) * sizeof(DWORD);
		}
		else
		{
			Request[t++] = TAG_GOODFORMAT;
			long* ptr = (long*)(Request+2);
			*ptr = m_lFindTotal;
			dwLen += sizeof(long);
		}
	}
	else
	{
		Request[1] = TAG_BADFORMAT;
	}

	if(SendData(m_clientSocket, Request, dwLen, 0) < 0)
		return FALSE;

	return ((AuthTagCounter == AUTH_MAGIC) || AuthRequest) ? AUTH_MAGIC : result;
}

volatile int threadno=0;

DWORD CRMSClientSocket::ThreadFunc()
{
	TRACE1("%x - CRMSClientSocket::ThreadFunc() - started\n", this);
	BYTE *pSrc;
	int nLen, i;
	int cycle;

	DWORD dwTag;
	DWORD dwLen;
	DWORD colTags;
	int result;

    NoVideo=0;
	m_bActive = true;

#ifdef mydebug
threadno++;
int tid=GetCurrentThreadId();
string tids = "_"+mdo.inttostr(threadno)+"_ ("+mdo.inttostr(tid)+"): ";
mdo.printstr("starting rmscs threadfunc ("+mdo.inttostr(tid)+")");
#endif

	SetThreadPriority(m_hThread,THREAD_PRIORITY_ABOVE_NORMAL);

#ifndef _RMS_TRANSLATOR_
#if defined(_OEM_) && defined(_TEC_)
	clientLog.startLogging(m_saClient.sin_addr.S_un.S_addr);
#endif //defined(_OEM_) && defined(_TEC_)
#endif //ndef _RMS_TRANSLATOR_

	result=GetClientRequest();
	if(!result)
	{
		goto error_exit1;
	}
	if(result==AUTH_MAGIC)
	{
#ifndef _RMS_TRANSLATOR_
#if defined(_OEM_) && defined(_TEC_)
		clientLog.message("%s%s", "", RingStringCopy);
#endif //defined(_OEM_) && defined(_TEC_)
#endif //ndef _RMS_TRANSLATOR_
		goto error_exit1;
	}
	if(m_bStored)
	{
		BOOL stop = FALSE;
#ifdef _CYCLIC_BUFFER_
		int j;
		CString temp;
		CTime timeCur((int)m_timeEnd.dwYear,
					  (int)m_timeEnd.bMonth,
					  (int)m_timeEnd.bDay,
					  (int)m_timeEnd.bHour,
					  (int)m_timeEnd.bMinute,
					  (int)m_timeEnd.bSecond);
		CTimeSpan timeSpan(1,0,0,0);
		for(j=pBaseServer->GetRecordCycle()-1; j>=0; j--) 
		{
			if(CameraID)
			{
				temp.Format("%i%s", CameraID, (LPCTSTR)timeCur.Format("%b%d%Y.rms"));
			}
			else
			{
				temp = timeCur.Format("%b%d%Y.rms");
			}
			if(temp == m_strBeginFile)
			{
				break;
			}
			timeCur -= timeSpan;
		}
#else
#if defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)

		// get all records which intersect with requested time interval
		int nfiles = 0;
		TimeMark* tms = getRecords(CameraID, m_timeStart, m_timeEnd, nfiles);
		if((tms == NULL) || (nfiles == 0))
		{
			if(tms != NULL) delete tms;
			goto error_exit;
		}

		if(m_bGetRecords)
		{ // were requested for records
			dwTag = 0;
			if((recv(m_clientSocket, (char*)&dwTag, 4, 0) != SOCKET_ERROR) && (dwTag == TAG_GETDATA))
			{
				colTags = 1;
				memcpy(m_pData, &colTags, 4);
				dwTag = TAG_TIMEMARK;
				memcpy(m_pData+4, &dwTag, 4);
				dwLen = nfiles * (2*sizeof(TimeMark));
				memcpy(m_pData+8, &dwLen, 4);
				memcpy(m_pData+12, tms, dwLen);
				dwLen += 12;
				if(SendData(m_clientSocket, m_pData, dwLen, &m_bQuit) >= 0) Sleep(1000);
			}
			delete tms;
			goto error_exit;
		}

		// prepare to playback the first found record
		CString fname;
		fname.Format("%d-%s-%s", CameraID, tms[0].toJNCString(), tms[1].toJNCString());
		delete tms;

		if(m_file)
		{
			fclose(m_file);
			m_file = NULL;
		}

		CString hp = getHomePath();
		hp += "\\"; hp += fname; hp += ".rms";
		m_file = fopen(hp, "rb");
		if(!m_file)
		{
			goto error_exit;
		}

		if(m_bTimeMark1)
		{
			m_timeStart = m_timeFrom;
			m_timeEnd = m_timeTo;
		}

		if(!getStartPosition(m_file))
		{
			goto error_exit;
		}

#else //defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)
		CString temp;
		if(m_file)
		{
			fclose(m_file);
			m_file = NULL;
		}
		if(CameraID)
		{
			temp.Format("%i",CameraID);
			temp += "stored_video.rms";
		}
		else
		{
			temp = "stored_video.rms";
		}
		CString hp = "";
#ifndef _VC10EA_
		hp = getHomePath();
		if(!hp.IsEmpty()) hp += "\\";
#endif //ndef _VC10EA_
		hp += temp;
		m_file = fopen(hp, "rb");
		if(!m_file)
		{
			goto error_exit;
		}

#endif //defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)
#endif

#ifdef _CYCLIC_BUFFER_
		for(; j<pBaseServer->GetRecordCycle(); j++)
		{
			if(m_file)
			{
				fclose(m_file);
				m_file = NULL;
			}
			CString hp = getHomePath();
			hp += "\\";
			hp += temp;
			m_file = fopen(hp, "rb");

			if(!m_file)
			{
				if(temp == m_strEndFile) goto error_exit;

				timeCur += timeSpan;
				if(CameraID)
				{
					temp.Format("%i%s", CameraID, (LPCTSTR)timeCur.Format("%b%d%Y.rms"));
				}
				else
				{
					temp = timeCur.Format("%b%d%Y.rms");
				}
				continue;
			}
			else
			{
				fpos_t pos = (temp == m_strBeginFile) ? sizeof(DWORD) + m_lBeginPosition
													  : sizeof(DWORD);
				fsetpos(m_file, &pos);
			}

			while(!m_bQuit && !feof(m_file) && !stop)
			{
				dwTag = 0;
				if (recv(m_clientSocket, (char*)&dwTag, 4, 0) == SOCKET_ERROR) 
				{
					goto error_exit;
				}

				if(dwTag != TAG_GETDATA)
				{
					goto error_exit;
				}
				else
				{
new_frame:
					pSrc = m_pData;

					nLen = 4;
					colTags = 0;
					pSrc += 4;

					nLen += 4;
					dwTag = TAG_STOREDDATA;
					memcpy(pSrc,&dwTag,4);
					pSrc += 4;
					colTags++;
					while(!m_bQuit && !feof(m_file))
					{
						dwTag = 0;
						EnterCriticalSection(pCriticalData);
						if(temp == m_strEndFile)
						{
							fpos_t pos;
							fgetpos(m_file, &pos);
							if(pos >= m_lEndPosition)
							{
								stop = TRUE;
							}
						}
						fread(&dwTag, 4, 1, m_file);
						LeaveCriticalSection(pCriticalData);
						if(dwTag == TAG_STOREDDATA)
						{
							break;
						}
						if(dwTag == TAG_SIZE)
						{
							EnterCriticalSection(pCriticalData);
							{ fpos_t tp; fgetpos(m_file, &tp); tp += sizeof(DWORD); fsetpos(m_file, &tp); }
							LeaveCriticalSection(pCriticalData);
							continue;
						}					
						if(dwTag == TAG_TIMEMARK)
						{
							TimeMark tm;
							EnterCriticalSection(pCriticalData);
							fread(&tm, sizeof(TimeMark), 1, m_file);
							LeaveCriticalSection(pCriticalData);
							nLen += sizeof(TimeMark) + sizeof(DWORD);
							memcpy(pSrc, &dwTag, sizeof(DWORD));
							pSrc += sizeof(DWORD);
							memcpy(pSrc, &tm, sizeof(TimeMark));
							pSrc += sizeof(TimeMark);
							colTags++;
							continue;
						}
						switch(dwTag)
						{
						case TAG_RMSSTOREDVIDEO_v01:
						case TAG_RMSSTOREDSOUND_v01:
						case TAG_STOREDTIME_v01:
						case TAG_STOREDDATE_v01:
							EnterCriticalSection(pCriticalData);
							memcpy(pSrc, &dwTag, sizeof(DWORD));
							pSrc += sizeof(DWORD);
							fread(&dwLen, sizeof(DWORD), 1, m_file);
							memcpy(pSrc, &dwLen, sizeof(DWORD));
							pSrc += sizeof(DWORD);
							fread(pSrc, 1, dwLen, m_file);
							pSrc += dwLen;
							nLen += dwLen + sizeof(DWORD)*2;
							colTags++;
							LeaveCriticalSection(pCriticalData);
							break;
						default:
							if(!FindFrame(m_file, 0))
							{
								goto error_exit;
							}
							{ fpos_t tp; fgetpos(m_file, &tp); tp += 4; fsetpos(m_file, &tp); }
							goto new_frame;
							break;
						}
					}

					if(m_bQuit) goto error_exit;
					memcpy(m_pData,&colTags,sizeof(DWORD));

					if (SendData(m_clientSocket,m_pData,nLen,&m_bQuit)<0)
						goto error_exit;
				}
			}
			if(stop) break;
			if(m_bQuit) goto error_exit;
			
			timeCur += timeSpan;
			if(CameraID)
			{
				temp.Format("%i%s", CameraID, (LPCTSTR)timeCur.Format("%b%d%Y.rms"));
			}
			else
			{
				temp = timeCur.Format("%b%d%Y.rms");
			}
		}
#else
		fpos_t pos = m_lBeginPosition + sizeof(DWORD);
		fsetpos(m_file, &pos);
		while(!m_bQuit && !feof(m_file) && !stop)
		{
			dwTag = 0;
			if (recv(m_clientSocket, (char*)&dwTag, 4, 0) == SOCKET_ERROR) 
			{
				goto error_exit;
			}

			if(dwTag != TAG_GETDATA)
			{
				goto error_exit;
			}
			else
			{
new_frame:
				pSrc = m_pData;

				nLen = 4;
				colTags = 0;
				pSrc += 4;

				nLen += 4;
				dwTag = TAG_STOREDDATA;
				memcpy(pSrc,&dwTag,4);
				pSrc += 4;
				colTags++;
				while(!m_bQuit && !feof(m_file))
				{
					fpos_t pos = 0;
					dwTag = 0;
					EnterCriticalSection(pCriticalData);
					fgetpos(m_file, &pos);
					if(pos >= m_lEndPosition)
					{
						stop = TRUE;
					}
					fread(&dwTag, 4, 1, m_file);
					LeaveCriticalSection(pCriticalData);
					if(dwTag == TAG_STOREDDATA)
					{
						break;
					}
					if(dwTag == TAG_SIZE)
					{
						EnterCriticalSection(pCriticalData);
						{ fpos_t tp; fgetpos(m_file, &tp); tp += sizeof(DWORD); fsetpos(m_file, &tp); }
						LeaveCriticalSection(pCriticalData);
						continue;
					}					
					if(dwTag == TAG_TIMEMARK)
					{
						TimeMark tm;
						EnterCriticalSection(pCriticalData);
						fread(&tm, sizeof(TimeMark), 1, m_file);
						LeaveCriticalSection(pCriticalData);
						nLen += sizeof(TimeMark) + sizeof(DWORD);
						memcpy(pSrc, &dwTag, sizeof(DWORD));
						pSrc += sizeof(DWORD);
						memcpy(pSrc, &tm, sizeof(TimeMark));
						pSrc += sizeof(TimeMark);
						colTags++;
						continue;
					}
					switch(dwTag)
					{
					case TAG_RMSSTOREDVIDEO_v01:
					case TAG_RMSSTOREDSOUND_v01:
					case TAG_STOREDTIME_v01:
					case TAG_STOREDDATE_v01:
						EnterCriticalSection(pCriticalData);
						memcpy(pSrc, &dwTag, sizeof(DWORD));
						pSrc += sizeof(DWORD);
						fread(&dwLen, sizeof(DWORD), 1, m_file);
						memcpy(pSrc, &dwLen, sizeof(DWORD));
						pSrc += sizeof(DWORD);
						fread(pSrc, 1, dwLen, m_file);
						pSrc += dwLen;
						nLen += dwLen + sizeof(DWORD)*2;
						colTags++;
						LeaveCriticalSection(pCriticalData);
						break;
					default:
						if(!FindFrame(m_file, 0))
						{
							goto error_exit;
						}
						{ fpos_t tp; fgetpos(m_file, &tp); tp += sizeof(DWORD); fsetpos(m_file, &tp); }
						goto new_frame;
						break;
					}
				}
				if(m_bQuit) goto error_exit;
				memcpy(m_pData,&colTags,sizeof(DWORD));

				if (SendData(m_clientSocket,m_pData,nLen,&m_bQuit)<0)
						goto error_exit;
			}
		}
#endif
		if(m_file)
		{
			fclose(m_file);
			m_file = NULL;
		}
	}
	else
	{
		cycle = 0;
#ifdef _VC10EA_
		((CVC10EACtrl*)pBaseServer)->OnClients();
#endif //def _VC10EA_

#ifndef _RMS_TRANSLATOR_
#if defined(_OEM_) && defined(_TEC_)
		clientLog.message("%s%s", "", RingStringCopy);
#endif //defined(_OEM_) && defined(_TEC_)
#endif //ndef _RMS_TRANSLATOR_

#ifdef mydebug
mdo.printstr(tids+"starting main cycle");
#endif
		while(!m_bQuit)
		{
#ifdef mydebug
mdo.printstr(tids+" - alive");
#endif
			EnterCriticalSection(pCriticalData);
//mdo.printstr(tids+"002");
			if((!(*pSzVideo)) && (!(*pSzDate)) && (!(*pSzTime)))
			{
				 LeaveCriticalSection(pCriticalData);
				if((cycle++) > SLEEP_CYCLE)
				{
					TRACE0("Unable to connect to camera.\n");
					goto error_exit;
				}
				Sleep(100);
				continue;
			}
//mdo.printstr(tids+"003");
			LeaveCriticalSection(pCriticalData);
			cycle = 0;

			dwTag = 0;
//mdo.printstr(tids+"004");
			if(recv(m_clientSocket, (char*)&dwTag, sizeof(DWORD), 0) == SOCKET_ERROR) 
			{
				goto error_exit;
			}
//mdo.printstr(tids+"005");
			colTags = 0;
			//	Send time
			if(dwTag != TAG_GETDATA)
			{
//mdo.printstr(tids+"006");
				if(dwTag == TAG_VC_RING)
				{
					memset(Caller, 0, sizeof(Caller));
					Caller[0] = TAG_VC_RING;
					if(recv(m_clientSocket, (char*)(Caller+1), sizeof(DWORD), 0) == SOCKET_ERROR) 
						goto error_exit;
					if(Caller[1] && (Caller[1] < 1000))
					{
						int n = recv(m_clientSocket, (char*)(Caller+2), Caller[1], 0);
						if(n == SOCKET_ERROR) goto error_exit;
						((char*)(Caller+2))[Caller[1]] = 0;
					}
					// send message to main application
#ifdef _RMS_TRANSLATOR_
					// send this ring to the video-camera socket
					pBaseServer->SengRing(CameraID, Caller);
#else
					// encoder- display incoming call dialog
					memcpy(RingString, &Caller[2], Caller[1]+1);
#ifndef _VC10EA_
					::PostMessage(AfxGetApp()->m_pMainWnd->GetSafeHwnd(), IDC_INCALL, (LONG)(Caller+2), 0);
					/*
					while (RingStatus==0) {
						if (m_bQuit) goto error_exit;
						Sleep(100);
					}*/
					RingStatus=TAG_GOODFORMAT;
#else //ndef _VC10EA_
					RingStatus=TAG_GOODFORMAT;
#endif //ndef _VC10EA_
					if(SendData(m_clientSocket, &RingStatus, sizeof(DWORD), &m_bQuit) < 0)
						goto error_exit;
					if(RingStatus != TAG_GOODFORMAT) goto error_exit;
#endif
				}
				else
					goto error_exit;
			}
			else
			{
//mdo.printstr(tids+"007");
				if(NewPassword)
				{
					dwTag = 0xBADF;
					memcpy(m_pData,&dwTag,sizeof(DWORD));
					if (SendData(m_clientSocket,m_pData,sizeof(DWORD),&m_bQuit)<0)
						goto error_exit;
					Sleep(100);
					goto error_exit;
				}
//mdo.printstr(tids+"008");
				pSrc = m_pData;

				nLen = sizeof(DWORD);
				colTags = 0;
				pSrc += sizeof(DWORD);

				//	Time
				while(1)
				{
					EnterCriticalSection(pCriticalData);
					// check for same size, to prevent sending 70 fps over LAN
					if(lastSendSize != *(DWORD*)pSzVideo) break;
					// send at least once a second, to prevent "disconnection on video lost"
					int diff = timeGetTime() - lastSendTime;
					if(diff > 1000)
					{
						printf("1");
						break;
					}
					LeaveCriticalSection(pCriticalData);
					Sleep(5);
					if(m_bQuit) goto error_exit;
				}
//mdo.printstr(tids+"009");
				lastSendSize=*(DWORD*)pSzVideo;
				lastSendTime=timeGetTime();
				LeaveCriticalSection(pCriticalData);

				if(m_bTime)
				{
					switch(m_dwTypeTime)
					{
					case TAG_TIME_v01:
						EnterCriticalSection(pCriticalData);
						if(*pSzTime)
						{
							nLen += *pSzTime+8;
							dwTag = TAG_TIME_v01;

							memcpy(pSrc,&dwTag,sizeof(DWORD));
							pSrc += sizeof(DWORD);
							memcpy(pSrc,pSzTime,sizeof(DWORD));
							pSrc += sizeof(DWORD);
							memcpy(pSrc,dtTime,*pSzTime);
							pSrc += *pSzTime;

							++colTags;
						}
						LeaveCriticalSection(pCriticalData);
						break;
					default:
						// This format of time is not supported
						break;
					}
				}
//mdo.printstr(tids+"010");
				//	Date
				if(m_bQuit) goto error_exit;
				if(m_bDate)
				{
					switch(m_dwTypeDate)
					{
					case TAG_DATE_v01:
						EnterCriticalSection(pCriticalData);
						if(*pSzDate)
						{
							nLen += *pSzDate+8;
							dwTag = TAG_DATE_v01;

							memcpy(pSrc,&dwTag,sizeof(DWORD));
							pSrc += sizeof(DWORD);
							memcpy(pSrc,pSzDate,sizeof(DWORD));
							pSrc += sizeof(DWORD);
							memcpy(pSrc,dtDate,*pSzDate);
							pSrc += *pSzDate;

							++colTags;
						}
						LeaveCriticalSection(pCriticalData);
						break;
					default:
						// This format of date is not supported
						break;
					}
				}
//mdo.printstr(tids+"011");
				//	Video
				if(m_bQuit) goto error_exit;
#ifndef _RMS_TRANSLATOR_
 #ifdef _NET_VC_
				if(m_bNoVideoEnabled)
				{
					DWORD dwWS = WaitForSingleObject(g_hNoVideoEnabled, 5000);
					if(dwWS != WAIT_OBJECT_0)
					{
						if(dwWS == WAIT_TIMEOUT)
						{
							goto respond;
						}
						goto error_exit;
					}
				}
 #endif //def _NET_VC_
#endif //ndef _RMS_TRANSLATOR_
_log(strtime()<<"NOVIDEO = "<<m_bNoVideoEnabled << "\n");
_log(strtime()<<"m_bVideo = "<<m_bVideo<<"\n");
                if (m_bNoVideoEnabled) NoVideo++; else NoVideo=0;

_log("NoVideo=" << NoVideo <<"\n");
_log("m_bVideo=" << m_bVideo <<"\n");

#ifdef _RMS_TRANSLATOR_
  NoVideo=0;
#endif
//mdo.printstr(tids+"012");
				if(m_bVideo && (NoVideo<=10))
				{
_log("m_dwTypeVideo="<<m_dwTypeVideo<<"\n");
					switch(m_dwTypeVideo)
					{
						case TAG_RMSVIDEO_v01:
						case TAG_RMSVIDEO_v02:
							EnterCriticalSection(pCriticalData);
							if(*pSzVideo)
							{
								nLen += *pSzVideo+8;
								//dwTag = TAG_RMSVIDEO_v01;
								dwTag = *pTypeVideo;

								memcpy(pSrc,&dwTag,sizeof(DWORD));
								pSrc += sizeof(DWORD);
								memcpy(pSrc,pSzVideo,sizeof(DWORD));
								pSrc += sizeof(DWORD);
								memcpy(pSrc,dtVideo,*pSzVideo);
								pSrc += *pSzVideo;
								++colTags;
							}
							LeaveCriticalSection(pCriticalData);
							break;
						default:
							// This format of video is not supported
							break;
					}
				}
			}
//mdo.printstr(tids+"013");
respond:
			if(m_bQuit) goto error_exit;
			if(colTags > 0)
			{
				memcpy(m_pData,&colTags,sizeof(DWORD));
				if (SendData(m_clientSocket,m_pData,nLen,&m_bQuit)<0)
						goto error_exit;
_log(strtime()<<"sending "<<nLen<<" bytes\n");
/*static int ttt=0;
ttt++;
if(ttt==40) m_bVideo=FALSE;*/
			}
			i=0;
//mdo.printstr(tids+"014");
		}
	}

error_exit:
	if(!m_bStored)
	{
		finish();
#ifdef _VC10EA_
		if(!m_bQuit)
			((CVC10EACtrl*)pBaseServer)->OnClients();
#endif //def _VC10EA_
		goto fin;
	}
error_exit1:
	finish();
fin:

#ifndef _RMS_TRANSLATOR_
#if defined(_OEM_) && defined(_TEC_)
	clientLog.stopLogging(TRUE);
#endif //defined(_OEM_) && defined(_TEC_)
#endif //ndef _RMS_TRANSLATOR_

	TRACE2("%x - CRMSClientSocket::ThreadFunc() - finished: %d\n", this, result);
	return 0;
}

void CRMSClientSocket::finish()
{
	if(m_clientSocket)
	{
		SOCKET socket = m_clientSocket;
		m_clientSocket=0;
		shutdown(socket, SD_BOTH);
		closesocket(socket);
	}

	if(m_file)
	{
		FILE* file = m_file;
		m_file = NULL;
		fclose(file);
	}

	if( m_bActive )
	{
		m_bActive = FALSE;
		if( m_byID != 0xFF )
			pBaseServer->TerminateWaveSesson(m_byID);
	}
}

void CRMSClientSocket::OnCriticalTerminate()
{
	TRACE1("%x - CRMSClientSocket::OnCriticalTerminate()\n", this);
	finish();
}
/*
DWORD CRMSClientSocket::Terminate(BOOL bCritical)
{
	TRACE2("%x - CRMSClientSocket::Terminate(), m_bQuit=%d\n", this, m_bQuit);

	if( m_bQuit ) return STATUS_WAIT_0; // return 0

	m_bQuit=1;
	finish();
	return CRMSThread::Terminate(bCritical);
}
*/

#if defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)

TimeMark* CRMSClientSocket::getRecords(int nCameraID, TimeMark& from, TimeMark& to, int& nfiles)
{
	CString str, str1, str2;
	CString criteria = getHomePath();
	str.Format(_T("\\%d-*"), nCameraID);
	criteria += str;

	// searching for any file
	int len, i;
	int cnt = 0;
	TimeMark* tms = NULL;
	WIN32_FIND_DATA fc;
	HANDLE h = FindFirstFile(criteria, &fc);
	if((h != NULL) && (h != INVALID_HANDLE_VALUE))
	{
		tms = new TimeMark[MAX_MARKERS];
		do
		{
			if((fc.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
			{
				str = fc.cFileName;
				str.MakeLower();
				len = str.GetLength();
				if((len <= (2+2*(3+2+4+2+2+2)+4)) || (len > (3+2+2*(3+2+4+2+2+2)+4)))
					continue;
				str.TrimRight(_T(".rms"));
				if((len - 4) != str.GetLength())
					continue;
				str2 = str.Right(3+2+4+2+2+2);	// ending date & time
				str.TrimRight(str2);
				str.TrimRight(_T('-'));
				str1 = str.Right(3+2+4+2+2+2);	// starting date & time
				str.TrimRight(str1);
				str.TrimRight(_T('-'));
				if(nCameraID != _ttoi(str))
					continue;
				TimeMark t1, t2;
				if(!t1.parseJNCString(str1))
					continue;
				if(!t2.parseJNCString(str2))
					continue;

				if((t2.toLong() < from.toLong()) || (t1.toLong() > to.toLong()))
					continue;

				tms[cnt++] = t1;
				tms[cnt++] = t2;
			}
		}
		while(FindNextFile(h, &fc));
		FindClose(h);
		if(cnt == 0)
		{
			delete tms;
			tms = NULL;
		}
	}
	nfiles = cnt / 2;
	return tms;
}
#endif //defined(_RMS_TRANSLATOR_) && defined(_JNC_REC_)

#ifndef _CYCLIC_BUFFER_
BOOL CRMSClientSocket::getStartPosition(FILE* f)
{
	BOOL finded = FALSE;
	int iRes = 0;
	fpos_t lBeginPosition, lEndPosition, lTestPosition;
	fpos_t lFindFirst = 0;
	fpos_t lFindLast = 0;
	m_lFindTotal = 0;
	m_lBeginPosition = 0;
	m_lEndPosition = 0;
	lBeginPosition = lEndPosition = lTestPosition = 0;

	// Find first frame
	fseek(f, 0L, SEEK_SET);
	fgetpos(f, &lBeginPosition);
	if(TimeCompare(f, m_timeStart, iRes) && (iRes >= 0))
	{
		fgetpos(f, &m_lBeginPosition);
		finded = TRUE;
	}
	else
	{
		fpos_t tp = _filelengthi64(fileno(f)); fsetpos(m_file, &tp);
		if(!FindFrame(f, 1)) goto stop_search;
		fgetpos(f, &lEndPosition);
		if(TimeCompare(f, m_timeStart, iRes) && (iRes >= 0))
		{
			finded = TRUE;
			while(!feof(f) && !m_bQuit)
			{
				fsetpos(f, &lBeginPosition);
				if((lEndPosition - lBeginPosition) <= GetFrameLength(f))
				{
					m_lBeginPosition = lEndPosition;
					lFindFirst = lEndPosition;
					break;
				}

				lTestPosition = lBeginPosition + (lEndPosition - lBeginPosition) / 2;
				fsetpos(f, &lTestPosition);
				if(!FindFrame(f, 0)) goto stop_search;

				fgetpos(f, &lTestPosition);
				if(lTestPosition == lBeginPosition)
				{
					m_lBeginPosition = lBeginPosition;
					lFindFirst = lBeginPosition;
					break;
				}
				if(lTestPosition == lEndPosition)
				{
					m_lBeginPosition = lEndPosition;
					lFindFirst = lEndPosition;
					break;
				}
				
				if(TimeCompare(f, m_timeStart, iRes) && (iRes >= 0))
				{
					lEndPosition = lTestPosition;
				}
				else
				{
					lBeginPosition = lTestPosition;
				}
			}
		}
	}

	if(finded)
	{
		// Find Last frame
		lBeginPosition = lFindFirst;
		lEndPosition = _filelengthi64(fileno(f)); fsetpos(m_file, &lEndPosition);

		if(!FindFrame(f, 1)) goto stop_search;

		if(TimeCompare(f, m_timeEnd, iRes) && (iRes <= 0))
		{
			fgetpos(f, &lFindLast);
			fsetpos(f, &lEndPosition);
			lFindLast = lEndPosition + GetFrameLength(f);
			m_lEndPosition = lFindLast;
			m_lFindTotal = lFindLast - lFindFirst;
		}
		else
		{
			while(!feof(f) && !m_bQuit)
			{
				fsetpos(f, &lBeginPosition);
				if((lEndPosition - lBeginPosition) <= GetFrameLength(f))
				{
					fsetpos(f, &lBeginPosition);
					lFindLast = lBeginPosition + GetFrameLength(f);
					m_lEndPosition = lFindLast;
					m_lFindTotal = lFindLast - lFindFirst;
					break;
				}

				lTestPosition = lBeginPosition + (lEndPosition - lBeginPosition) / 2;
				fsetpos(f, &lTestPosition);
				if(!FindFrame(f, 0)) goto stop_search;

				fgetpos(f, &lTestPosition);
				if(lTestPosition == lBeginPosition)
				{
					fsetpos(f, &lBeginPosition);
					lFindLast = lBeginPosition + GetFrameLength(f);
					m_lEndPosition = lFindLast;
					m_lFindTotal = lFindLast - lFindFirst;
					break;
				}
				if(lTestPosition == lEndPosition)
				{
					fsetpos(f, &lEndPosition);
					lFindLast = lEndPosition + GetFrameLength(f);
					m_lEndPosition = lFindLast;
					m_lFindTotal = lFindLast - lFindFirst;
					break;
				}
				
				if(TimeCompare(f, m_timeEnd, iRes) && (iRes >= 0))
				{
					lEndPosition = lTestPosition;
				}
				else
				{
					lBeginPosition = lTestPosition;
				}
			}
		}
	}
stop_search:

	return (m_lFindTotal != 0);
}
#endif //ndef _CYCLIC_BUFFER_
#ifdef _IPR_
BOOL CRMSClientSocket::IsRegistedIP(in_addr sin_addr)
{
	bool findFlg = false;
	map<CString, CAllowIP> * m_pRegistIp;
	m_pRegistIp = &pBaseServer->m_registIp;
	map<CString, CNetmask> *  m_pNetmask;
	map<CString,CAllowIP>::const_iterator pIp;
	map<CString, CNetmask>::const_iterator pNet;

	EnterCriticalSection(&pBaseServer->m_IprCritical);
	for(pIp = pBaseServer->m_registIp.begin(); pIp != pBaseServer->m_registIp.end(); pIp++)
	{
		for(pNet = (pIp->second).m_Netmask.begin(); pNet != (pIp->second).m_Netmask.end(); pNet++)
		{
			ULONG subnetmask = (0xffffffff >> (32-(pNet->second).m_netmask)) << (32-(pNet->second).m_netmask);
			BYTE b_subnet[4];
			b_subnet[0] = subnetmask >> 24;
			b_subnet[1] = subnetmask >> 16;
			b_subnet[2] = subnetmask >> 8;
			b_subnet[3] = subnetmask;
			subnetmask = (ULONG)b_subnet[3]<<24 | (ULONG)b_subnet[2]<<16 | (ULONG)b_subnet[1]<<8 | (ULONG)b_subnet[0];

			in_addr i_netid;
			i_netid.S_un.S_addr = sin_addr.S_un.S_addr & subnetmask;
			CString netid = inet_ntoa(i_netid);
			if (netid == (pNet->second).m_netid)
			{
				findFlg = true;
				break;
			}
		}
		if (findFlg)
		{
			break;
		}
	}
	LeaveCriticalSection(&pBaseServer->m_IprCritical);
	return findFlg;
}
#endif //def _IPR_